package com.cn.netty.customize.server;

import com.cn.netty.customize.handler.DecodeHandler;
import com.cn.netty.customize.handler.EncodeHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Server {

  public static void main(String[] args) {
    EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
    ServerBootstrap bootstrap = new ServerBootstrap();
    ServerBootstrap serverBootstrap = bootstrap.group(eventLoopGroup)
            .channel(NioServerSocketChannel.class)
            .localAddress(9999).childHandler( //注意 这是个childHandler
                    new ChannelInitializer<SocketChannel>() {
                      @Override
                      protected void initChannel(SocketChannel ch) throws Exception {

                        ch.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));

                        ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535,
                                0, 2, 0,
                                2));//入站  粘包拆包解码

                        ch.pipeline().addLast(new LengthFieldPrepender(2));//出站  "粘包拆包"编码

                        ch.pipeline().addLast(new EncodeHandler()); //出站 编码
                        ch.pipeline().addLast(new DecodeHandler()); //入站 解码

                        ch.pipeline().addLast(new ReadTimeoutHandler(10));//10秒 读空闲，抛出异常

                        ch.pipeline().addLast(new HearBeatResHandler()); //心跳

                        ch.pipeline().addLast(new BusinessHandler());

                      }
                    });
    try {
      /*异步绑定到服务器，sync()会阻塞到完成*/
      ChannelFuture f = serverBootstrap.bind().sync();
      log.info("服务器启动完成。");
      /*阻塞当前线程，直到服务器的ServerChannel被关闭*/
      f.channel().closeFuture().sync();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

}
